import logging
from celery import shared_task
from django.utils import timezone
from datetime import timedelta
from projects.models import Project, Message
from projects.webhook_service import WebhookService
from .models import ScheduledTask, TaskExecutionLog
from .task_scheduler import check_and_schedule_tasks, execute_scheduled_task

logger = logging.getLogger(__name__)

@shared_task
def collect_and_push_pending_items():
    """
    定期收集系统内待处理事项，按项目维度分类汇总，并通过Webhook推送
    
    收集规则：
    1. 获取所有未处理的消息
    2. 按项目维度分类汇总
    3. 为每个项目生成汇总信息
    4. 通过Webhook推送汇总信息
    """
    try:
        # 创建执行日志记录
        log_entry = TaskExecutionLog.objects.create(
            task_id=None,  # 全局任务，无特定关联任务
            is_success=False
        )
        
        # 记录开始执行时间
        log_content = [f"任务开始执行: {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}"]
        
        # 获取所有未处理的消息（最近7天内创建的，包含更多状态）
        week_ago = timezone.now() - timedelta(days=7)
        pending_messages = Message.objects.filter(
            status__in=['pending', 'processing'],  # 包含待处理和处理中的消息
            created_at__gte=week_ago
        ).select_related('project').order_by('project', '-created_at')
        
        log_content.append(f"找到{pending_messages.count()}条未处理消息")
        
        # 按项目维度分类汇总
        project_messages = {}
        for message in pending_messages:
            if message.project.id not in project_messages:
                project_messages[message.project.id] = {
                    'project': message.project,
                    'messages': []
                }
            project_messages[message.project.id]['messages'].append(message)
        
        log_content.append(f"按项目分类后共有{len(project_messages)}个项目有待处理消息")
        
        # 初始化统计数据
        total_processed = 0
        success_count = 0
        failure_count = 0
        
        # 为每个项目生成汇总信息并推送
        for project_id, project_data in project_messages.items():
            project = project_data['project']
            messages = project_data['messages']
            
            total_processed += 1
            
            try:
                # 生成汇总信息
                summary = generate_summary(project, messages)
                
                # 推送汇总信息到Webhook
                push_summary_to_webhook(project, summary)
                
                success_count += 1
                log_content.append(f"成功推送项目{project.name}的汇总信息")
            except Exception as e:
                failure_count += 1
                error_msg = f"推送项目{project.name}的汇总信息失败: {str(e)}"
                log_content.append(error_msg)
                logger.error(error_msg)
        
        # 更新执行日志
        log_entry.end_time = timezone.now()
        log_entry.is_success = True
        log_entry.log_content = '\n'.join(log_content)
        log_entry.total_processed = total_processed
        log_entry.success_count = success_count
        log_entry.failure_count = failure_count
        log_entry.save()
        
        return {
            'status': 'success',
            'total_processed': total_processed,
            'success_count': success_count,
            'failure_count': failure_count
        }
        
    except Exception as e:
        # 记录执行错误
        if 'log_entry' in locals():
            log_entry.end_time = timezone.now()
            log_entry.is_success = False
            log_entry.error_message = str(e)
            log_entry.save()
        
        logger.error(f"执行待处理事项收集推送任务失败: {str(e)}")
        
        return {
            'status': 'failure',
            'error': str(e)
        }

def generate_summary(project, messages):
    """
    为指定项目和消息生成详细汇总信息
    """
    # 按消息类型分类
    message_by_type = {}
    message_by_status = {}
    message_by_date = {}
    
    for msg in messages:
        # 按类型统计
        if msg.message_type not in message_by_type:
            message_by_type[msg.message_type] = []
        message_by_type[msg.message_type].append(msg)
        
        # 按状态统计
        if msg.status not in message_by_status:
            message_by_status[msg.status] = []
        message_by_status[msg.status].append(msg)
        
        # 按日期统计（最近7天）
        date_key = msg.created_at.strftime('%Y-%m-%d')
        if date_key not in message_by_date:
            message_by_date[date_key] = []
        message_by_date[date_key].append(msg)
    
    # 构建详细汇总信息
    summary = {
        'project_id': str(project.id),
        'project_name': project.name,
        'project_description': project.description or '',
        'total_pending_count': len(messages),
        'pending_by_type': {},
        'pending_by_status': {},
        'pending_by_date': {},
        'messages': [],
        'statistics': {
            'oldest_message_date': None,
            'newest_message_date': None,
            'total_types': len(message_by_type),
            'average_per_day': 0
        },
        'timestamp': timezone.now().isoformat(),
        'summary_time': timezone.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    
    # 添加按类型统计
    for msg_type, msg_list in message_by_type.items():
        summary['pending_by_type'][msg_type] = len(msg_list)
    
    # 添加按状态统计
    for status, msg_list in message_by_status.items():
        summary['pending_by_status'][status] = len(msg_list)
    
    # 添加按日期统计
    for date, msg_list in message_by_date.items():
        summary['pending_by_date'][date] = len(msg_list)
    
    # 计算统计信息
    if messages:
        dates = [msg.created_at for msg in messages]
        summary['statistics']['oldest_message_date'] = min(dates).strftime('%Y-%m-%d %H:%M:%S')
        summary['statistics']['newest_message_date'] = max(dates).strftime('%Y-%m-%d %H:%M:%S')
        
        # 计算平均每日消息数
        date_range = (max(dates) - min(dates)).days + 1
        summary['statistics']['average_per_day'] = round(len(messages) / max(date_range, 1), 2)
    
    # 添加消息摘要（最多显示10条，按创建时间倒序）
    sorted_messages = sorted(messages, key=lambda x: x.created_at, reverse=True)
    for msg in sorted_messages[:10]:
        summary['messages'].append({
            'id': str(msg.id),
            'title': msg.title,
            'type': msg.message_type,
            'status': msg.status,
            'created_at': msg.created_at.strftime('%Y-%m-%d %H:%M:%S'),
            'source_data': msg.source_data
        })
    
    # 如果有超过10条消息，添加提示
    if len(messages) > 10:
        summary['more_messages_count'] = len(messages) - 10
    
    return summary

def push_summary_to_webhook(project, summary):
    """
    通过Webhook推送汇总信息
    只推送到事件类型为'push'的渠道
    """
    # 构建推送内容
    payload = {
        'event': 'pending_items_summary',
        'summary': summary,
        'alert_text': '详情点击报警平台',  # 包含引导文本
        'generated_at': timezone.now().isoformat()
    }
    
    # 触发webhook通知，使用'push'事件类型
    WebhookService.trigger_webhook('push', payload, project)
    
    logger.info(f"已推送项目{project.name}的待处理事项汇总信息")

# 注册定时任务
@shared_task
def scan_unread_messages_and_push():
    """
    按周期扫描归属项目未读消息，统计未读消息条数，将统计消息发送给事件类型为push的webhooks
    发送消息内容：项目名称，未读消息数，访问链接
    """
    try:
        # 创建执行日志记录
        log_entry = TaskExecutionLog.objects.create(
            task_id=None,  # 全局任务，无特定关联任务
            is_success=False
        )
        
        # 记录开始执行时间
        log_content = [f"任务开始执行: {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}"]
        
        # 获取所有项目
        projects = Project.objects.all()
        log_content.append(f"找到{projects.count()}个项目")
        
        # 初始化统计数据
        total_processed = 0
        success_count = 0
        failure_count = 0
        
        # 为每个项目扫描未读消息
        for project in projects:
            total_processed += 1
            
            try:
                # 统计该项目的未读消息数量（status='pending'）
                unread_count = Message.objects.filter(
                    project=project,
                    status='pending'
                ).count()
                
                # 只有当有未读消息时才推送
                if unread_count > 0:
                    # 创建统计消息内容
                    unread_summary = {
                        'project_name': project.name,
                        'unread_count': unread_count,
                        'access_link': f"/projects/{project.id}/messages/",  # 访问链接
                        'timestamp': timezone.now().isoformat(),
                        'summary_time': timezone.now().strftime('%Y-%m-%d %H:%M:%S')
                    }
                    
                    # 推送统计信息到Webhook
                    WebhookService.trigger_webhook('push', unread_summary, project)
                    
                    success_count += 1
                    log_content.append(f"成功推送项目{project.name}的未读消息统计，数量：{unread_count}")
                else:
                    log_content.append(f"项目{project.name}没有未读消息，跳过推送")
                    
            except Exception as e:
                failure_count += 1
                error_msg = f"推送项目{project.name}的未读消息统计失败: {str(e)}"
                log_content.append(error_msg)
                logger.error(error_msg)
        
        # 更新执行日志
        log_entry.end_time = timezone.now()
        log_entry.is_success = True
        log_entry.log_content = '\n'.join(log_content)
        log_entry.total_processed = total_processed
        log_entry.success_count = success_count
        log_entry.failure_count = failure_count
        log_entry.save()
        
        return {
            'status': 'success',
            'total_processed': total_processed,
            'success_count': success_count,
            'failure_count': failure_count
        }
        
    except Exception as e:
        # 记录执行错误
        if 'log_entry' in locals():
            log_entry.end_time = timezone.now()
            log_entry.is_success = False
            log_entry.error_message = str(e)
            log_entry.save()
        
        logger.error(f"执行未读消息扫描推送任务失败: {str(e)}")
        
        return {
            'status': 'failure',
            'error': str(e)
        }


def register_scheduled_tasks():
    """
    注册所有定时任务
    这个函数会在Django启动时被调用
    """
    from celery.schedules import crontab
    from baojing.celery import app
    
    # 清除所有现有的任务调度
    for key in list(app.conf.beat_schedule.keys()):
        if key.startswith('scheduled-task-'):
            del app.conf.beat_schedule[key]
    
    # 添加任务调度器（每分钟检查一次）
    app.conf.beat_schedule['check-and-schedule-tasks'] = {
        'task': 'tasks.task_scheduler.check_and_schedule_tasks',
        'schedule': crontab(minute='*'),  # 每分钟执行一次
        'args': ()
    }
    
    # 添加未读消息扫描任务（每小时执行一次）
    app.conf.beat_schedule['scan-unread-messages-and-push'] = {
        'task': 'tasks.tasks.scan_unread_messages_and_push',
        'schedule': crontab(minute=0),  # 每小时执行一次
        'args': ()
    }
    
    # 添加未处理消息统计推送任务（每小时执行一次）
    app.conf.beat_schedule['summarize-pending-messages-and-push'] = {
        'task': 'tasks.scheduled_summary.summarize_pending_messages_and_push',
        'schedule': crontab(minute=30),  # 每小时的第30分钟执行一次
        'args': ()
    }
    
    logger.info("已注册未读消息扫描任务：每小时执行一次")
    logger.info("已注册未处理消息统计推送任务：每小时执行一次")
    logger.info("已注册任务调度器：每分钟检查一次系统中的定时任务")